//封装数据服务
import CryptoJS from 'crypto-js'
import { APP_GLOBAL } from '@v-model/shared--constants'
import { http } from '@v-model/shared--utils'
import TAFFY from './taffy.js'

/*
new JsonStore({
	sql: sql,
	pageSize:5,
	error:function(status){
	},
	success:function(ds){//store对象

	}
});
*/

class JsonStore {
  config: any = {}
  service: string = APP_GLOBAL.API['FUNC']['sqlstore']
  dataSource: string = ''
  table: string = ''
  sql: string = ''
  IgnoreChange: boolean
  dataSet: any = {}
  cache: any = {
    save: [],
    remove: [],
    update: [],
  }
  root: any = {}
  count: number = 0
  totalCount: number = 0
  key: any = null
  command: string = 'init'
  start: number = 0
  page: number = 0
  pages: number = 0
  pageSize: any = ''
  columnModel: any = {}
  constructor(options: any) {
    this.IgnoreChange = false
    this.init(options)
  }
  init(options: any) {
    if (options && typeof options === 'object') {
      this.config = Object.assign({}, this.config, options)
    }
    this.service = this.config.service || APP_GLOBAL.API['FUNC']['datastore']
    this.sql = this.config.sql || this.sql
    this.dataSource = this.config.dataSource || this.dataSource
    this.table = this.config.table || this.table
    this.key = this.config.key || this.key
    this.command = 'init'
    this.pageSize = this.config.pageSize || this.pageSize || 20
    this.page = this.config.page || 1 //传入分页
    this.start = this.config.start || 0
    this.IgnoreChange = false ///是否忽略修改，如果设置为true，则此期间的修改不会保存到缓存，也不会提交到数据库
    this.count = 0
    this.totalCount = 0
    this.cache = {
      save: [],
      remove: [],
      update: [],
    }
    if (this.config.data) {
      this.root = this.config.data
      this.dataSet = TAFFY(this.config.data)
      this.count = this.config.data.length
      this.totalCount = this.config.data.length
    } else {
      var data = {
        initSql: this.encrypt(encodeURIComponent(this.sql)), //this.encrypt(encodeURI(this.sql)),
        command: this.command,
        dataSource: this.dataSource,
        limit: this.pageSize,
        start: this.start,
        root: 'root',
      }
      http
        .request('post', this.service + '/' + this.command, data)
        .then((response: any) => {
          //console.log(response.data)
          var dataJson = response
          if (dataJson.message && dataJson.message.indexOf('有错误') >= 0) {
            alert('数据查询出错,请联系系统管理员！')
            console.log('查询SQL语句: ' + this.sql)
          }
          if (dataJson) {
            this.totalCount = dataJson.total
            this.root = dataJson.root
            this.columnModel = dataJson.columnModel
            this.dataSet = TAFFY(dataJson.root)
          }
          //页码
          this.pages = 1
          if (this.pageSize && this.pageSize > 0 && this.totalCount) {
            this.pages = Math.ceil(this.totalCount / this.pageSize)
            if (this.pages < 1) {
              this.pages = 1
            }
          }
          if (dataJson.root) {
            this.count = dataJson.root.length
          }
          this.dataSet.settings({
            onUpdate: function () {},
            onInsert: function () {},
          })
          if (typeof this.config.success == 'function') {
            this.config.success(this)
          }
        })
        .catch((err: any) => {
          console.log(err)
          if (typeof this.config.error == 'function') {
            this.config.error(err)
          }
        })
    }
  }
  load(params: any) {
    var options = this.config
    if (params) {
      options = Object.assign({}, options, params)
    }
    this.init(options)
  }
  encrypt(val: string) {
    var wordArray = CryptoJS.enc.Utf8.parse(val)
    var base64 = CryptoJS.enc.Base64.stringify(wordArray)
    return base64
  }
  commit(async: boolean) {
    var isAsync = true
    if (async == false) {
      isAsync = false
    }
    var params: any = {}
    params.isAsync = isAsync
    params.dataSource = this.dataSource

    return new Promise((resolve, reject) => {
      if (this.cache.save.length > 0) {
        params.command = 'insert'
        params.records = JSON.stringify(this.cache.save)
        params.table = this.table
        params.key = this.key
        http.request('post', this.service + '/' + params.command, params).then((response: any) => {
          if (response.success == true) {
            resolve(response)
          } else {
            reject(response)
          }
        })
      } else {
        resolve(null)
      }
    })
      .then((response: any) => {
        return new Promise((resolve, reject) => {
          if (this.cache.update.length > 0) {
            params.command = 'update'
            params.records = JSON.stringify(this.cache.update)
            params.table = this.table
            params.key = this.key
            http.request('post', this.service + '/' + params.command, params).then((response: any) => {
              if (response.success == true) {
                resolve(response)
              } else {
                reject(response)
              }
            })
          } else {
            resolve(response)
          }
        })
      })
      .then((response: any) => {
        return new Promise((resolve, reject) => {
          if (this.cache.remove.length > 0) {
            params.command = 'delete'
            params.records = JSON.stringify(this.cache.remove)
            params.table = this.table
            params.key = this.key
            http.request('post', this.service + '/' + params.command, params).then((response: any) => {
              if (response.success == true) {
                resolve(response)
              } else {
                reject(response)
              }
            })
          } else {
            resolve(response)
          }
        })
      })
      .then((response: any) => {
        return new Promise((resolve, reject) => {
          this.cache.save.length = 0
          this.cache.remove.length = 0
          this.cache.update.length = 0
          resolve(response)
        })
      })
  }
  getNewRecord(initValCfg: any) {
    /*根据store的defautlValue来生成新的记录*/
    initValCfg = initValCfg || {}
    let rec = new record(initValCfg, this)
    return rec
  }
  getAt(i: number) {
    let resultJson = this.dataSet().getAt(i)
    if (resultJson) return new record(resultJson, this)
    else return null
  }
  add(r: any) {
    if (this.IgnoreChange) return
    this.dataSet.insert(r.data)
    //主键为空处理
    if (!r.data[this.key]) {
      delete r.data[this.key]
    }
    this.cache.save.push(r.data)
    var newItem: any = {}
    for (var key in r.data) {
      newItem[key] = r.data[key]
    }
    this.root.push(newItem)
    this.count++
    this.totalCount++
  }
  remove(r: any) {
    if (this.IgnoreChange) return
    var hadInRemove = false
    for (var i = 0; i < this.cache.save.length; i++) {
      //从新增的记录中删除
    }
    for (var i = 0; i < this.cache.remove.length; i++) {
      var hadRemoveRec = this.cache.remove[i]
      if (hadRemoveRec.___id == r.___id) {
        hadInRemove = true
        break
      }
    }
    if (!hadInRemove) {
      this.cache.remove.push(r.data)
    }
    this.dataSet().getDBI().remove(r.data.___id)
    this.dataSet().getDBI().removeCommit()
  }
  update(recJsonData: any, propertyName: any, value: any, oldvalue: any) {
    if (this.IgnoreChange) return
    var keys = this.key
    var tableKey = keys.split(',')
    var isSave = false
    var isUpdate = false
    var modify: any = {}
    for (var i = 0; i < this.cache.update.length; i++) {
      var hadUpdateRec = this.cache.update[i]
      if (hadUpdateRec.___id == recJsonData.___id) {
        modify = hadUpdateRec
        break
      }
    }
    if (modify) {
      modify[propertyName] = value
    } else {
      modify = {}
      for (var i = 0; i < tableKey.length; i++) {
        modify[tableKey[i]] = recJsonData[tableKey[i]]
      }
      modify[propertyName] = value
      this.cache.update.push(modify)
    }
  }
  getCount() {
    return this.dataSet().count()
  }
  getRecordByKey(keyValue: string) {
    /*根据当前主键返回记录*/
    if (!this.key) {
      alert('没有设置store主键,无法调用此函数: getRecordByKey')
      return
    }
    if (keyValue == undefined) {
      return
    }
    var _keys = this.key.split(',')
    var _keyValues = ('' + keyValue).split(',')
    if (_keys.length === _keyValues.length) {
      for (var i = 0; i < this.getCount(); i++) {
        var r: any = this.getAt(i)
        var _flag = true
        for (var j = 0; j < _keys.length; j++) {
          if (r.get(_keys[j]) != _keyValues[j]) {
            _flag = false
          }
        }
        if (_flag) {
          return r
        }
      }
    }
    return null
  }
}
class record {
  data: any = {}
  store: any = {}
  constructor(datajson: any, scope: any) {
    this.data = datajson
    this.store = scope
  }
  get(propertyName: any) {
    return this.data[propertyName]
  }
  set(propertyName: any, value: any) {
    //替换注存在xss漏洞，插入有特殊字符的代码，成功弹窗执行<<SCRIPT>alert("XSS");//<</SCRIPT>
    var val = ''
    if (typeof value == 'string') {
      var tmpVal = value.toLowerCase().replace(' ', '')
      if (
        tmpVal.indexOf('<script') > 0 ||
        tmpVal.indexOf('</script>') > 0 ||
        tmpVal.indexOf('<object') > 0 ||
        tmpVal.indexOf('</object>') > 0
      ) {
        val = value.replace(/<\/?[^>]*>/g, '')
      } else {
        val = value
      }
    } else {
      val = value
    }
    value = val
    if (!this.data.___id) {
      ///刚刚新增的
      this.data[propertyName] = value
      return true
    }
    ///新增缓存处理
    for (var i = 0; i < this.store.cache.save.length; i += 1) {
      if (this.store.cache.save[i].___id == this.data.___id) {
        this.store.cache.save[i][propertyName] = value
        return
      }
    }
    ///更新缓存处理
    var inUpdate = false
    for (var i = 0; i < this.store.cache.update.length; i += 1) {
      if (this.store.cache.update[i].___id == this.data.___id) {
        //console.log('已经在缓存中存在,进行更新');
        this.store.cache.update[i][propertyName] = value
        inUpdate = true
        break
      }
    }
    if (!inUpdate) {
      //console.log('不在缓存中存在,进行更新登记');
      this.data[propertyName] = value
      this.store.cache.update.push(this.data)
    }

    if (!this.store.IgnoreChange && this.data.___id) {
      ///变更真正的数据
      var changeCfg: any = {}
      changeCfg[propertyName] = value
      this.store.dataSet(this.data.___id).update(changeCfg) ///变更真正的数据
    }
  }
}
export default JsonStore
/*
export default (app: any) => {
    app.config.globalProperties.$JsonStore = JsonStore;
}
*/
